home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / DirectInput / Mouse / mouse.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  26.9 KB  |  716 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Mouse.cpp
  3. //
  4. // Desc: The Mouse sample show how to use a DirectInput mouse device and 
  5. //       the differences between cooperative levels and data styles. 
  6. //
  7. // Copyright (c) Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #define DIRECTINPUT_VERSION 0x0800
  11.  
  12. #include <tchar.h>
  13. #include <windows.h>
  14. #include <commctrl.h>
  15. #include <basetsd.h>
  16. #include <dinput.h>
  17. #include <stdio.h>
  18. #include "resource.h"
  19.  
  20.  
  21.  
  22.  
  23. //-----------------------------------------------------------------------------
  24. // Function-prototypes
  25. //-----------------------------------------------------------------------------
  26. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  27. HRESULT OnInitDialog( HWND hDlg );
  28. VOID    UpdateUI( HWND hDlg );
  29. HRESULT OnCreateDevice( HWND hDlg );
  30. HRESULT ReadImmediateData( HWND hDlg );
  31. HRESULT ReadBufferedData( HWND hDlg );
  32. VOID    FreeDirectInput();
  33.  
  34.  
  35.  
  36.  
  37. //-----------------------------------------------------------------------------
  38. // Defines, constants, and global variables
  39. //-----------------------------------------------------------------------------
  40. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  41. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  42.  
  43. #define SAMPLE_BUFFER_SIZE  16      // arbitrary number of buffer elements
  44. LPDIRECTINPUT8       g_pDI    = NULL;         
  45. LPDIRECTINPUTDEVICE8 g_pMouse = NULL;     
  46.  
  47.  
  48.  
  49.  
  50. //-----------------------------------------------------------------------------
  51. // Name: WinMain()
  52. // Desc: Entry point for the application.  Since we use a simple dialog for 
  53. //       user interaction we don't need to pump messages.
  54. //-----------------------------------------------------------------------------
  55. int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
  56. {
  57.     InitCommonControls();
  58.  
  59.     // Display the main dialog box.
  60.     DialogBox( hInst, MAKEINTRESOURCE(IDD_MOUSE), NULL, MainDlgProc );
  61.     
  62.     return TRUE;
  63. }
  64.  
  65.  
  66.  
  67.  
  68.  
  69. //-----------------------------------------------------------------------------
  70. // Name: MainDlgProc()
  71. // Desc: Handles dialog messages
  72. //-----------------------------------------------------------------------------
  73. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  74. {
  75.     switch( msg ) 
  76.     {
  77.         case WM_INITDIALOG:
  78.             OnInitDialog( hDlg );
  79.             break;
  80.         
  81.         case WM_COMMAND:
  82.             switch( LOWORD(wParam) )
  83.             {
  84.                 case IDCANCEL:
  85.                     EndDialog( hDlg, 0 ); 
  86.                     break;
  87.  
  88.                 case IDC_EXCLUSIVE:
  89.                 case IDC_NONEXCLUSIVE:
  90.                 case IDC_FOREGROUND:
  91.                 case IDC_BACKGROUND:
  92.                 case IDC_IMMEDIATE:
  93.                 case IDC_BUFFERED:
  94.                     UpdateUI( hDlg );
  95.                     break;
  96.  
  97.                 case IDM_CREATEDEVICE:
  98.                 case IDM_RELEASEDEVICE:
  99.                 case IDC_CREATEDEVICE:
  100.                     if( NULL == g_pMouse )
  101.                     {                    
  102.                         if( FAILED( OnCreateDevice( hDlg ) ) )
  103.                         {
  104.                             MessageBox( hDlg, _T("CreateDevice() failed. ")
  105.                                               _T("The sample will now exit. "), 
  106.                                               _T("Mouse"), MB_ICONERROR | MB_OK );
  107.                             FreeDirectInput();
  108.                         }
  109.  
  110.                         SetFocus( GetDlgItem( hDlg, IDC_CREATEDEVICE ) );
  111.                     }
  112.                     else
  113.                     {
  114.                         FreeDirectInput();
  115.                     }
  116.  
  117.                     UpdateUI( hDlg );
  118.                     break;
  119.  
  120.                 default:
  121.                     return FALSE; // Message not handled 
  122.             }       
  123.             break;
  124.  
  125.         case WM_ENTERMENULOOP:
  126.             // Release the device, so if we are in exclusive mode the 
  127.             // cursor will reappear
  128.             if( g_pMouse )
  129.             {
  130.                 g_pMouse->Unacquire();
  131.                 KillTimer( hDlg, 0 );  // Stop timer, so device is not re-acquired
  132.                 SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  133.             }
  134.             break;
  135.  
  136.         case WM_EXITMENULOOP:
  137.             // Make sure the device is acquired when coming out of a menu loop
  138.             if( g_pMouse )
  139.             {
  140.                 g_pMouse->Acquire();
  141.                 SetTimer( hDlg, 0, 1000 / 12, NULL ); // Start timer again
  142.             }
  143.             break;
  144.  
  145.         case WM_ACTIVATE:
  146.             if( WA_INACTIVE != wParam && g_pMouse )
  147.             {
  148.                 // Make sure the device is acquired, if we are gaining focus.
  149.                 g_pMouse->Acquire();
  150.             }
  151.             break;
  152.         
  153.         case WM_TIMER:
  154.             // Update the input device every timer message
  155.             {
  156.                 BOOL bImmediate = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  157.  
  158.                 if( bImmediate )
  159.                 {
  160.                     if( FAILED( ReadImmediateData( hDlg ) ) )
  161.                     {
  162.                         KillTimer( hDlg, 0 );    
  163.                         MessageBox( NULL, _T("Error Reading Input State. ")
  164.                                           _T("The sample will now exit. "), 
  165.                                           _T("Mouse"), MB_ICONERROR | MB_OK );
  166.                         EndDialog( hDlg, TRUE ); 
  167.                     }
  168.                 }
  169.                 else
  170.                 {
  171.                     if( FAILED( ReadBufferedData( hDlg ) ) )
  172.                     {
  173.                         KillTimer( hDlg, 0 );    
  174.                         MessageBox( NULL, _T("Error Reading Input State. ")
  175.                                           _T("The sample will now exit. "), 
  176.                                           _T("Mouse"), MB_ICONERROR | MB_OK );
  177.                         EndDialog( hDlg, TRUE ); 
  178.                     }
  179.                 }
  180.             }
  181.             break;
  182.         
  183.         case WM_DESTROY:
  184.             // Cleanup everything
  185.             KillTimer( hDlg, 0 );    
  186.             FreeDirectInput();    
  187.             break;
  188.  
  189.         default:
  190.             return FALSE; // Message not handled 
  191.     }
  192.  
  193.     return TRUE; // Message handled 
  194. }
  195.  
  196.  
  197.  
  198.  
  199. //-----------------------------------------------------------------------------
  200. // Name: OnInitDialog()
  201. // Desc: Initialize the DirectInput variables.
  202. //-----------------------------------------------------------------------------
  203. HRESULT OnInitDialog( HWND hDlg )
  204. {
  205.     // Load the icon
  206. #ifdef _WIN64
  207.     HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  208. #else
  209.     HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  210. #endif
  211.     HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  212.  
  213.     // Set the icon for this dialog.
  214.     PostMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  215.     PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  216.  
  217.     // Check the 'exclusive', 'foreground', and 'immediate' buttons by default. 
  218.     CheckRadioButton( hDlg, IDC_EXCLUSIVE,  IDC_NONEXCLUSIVE, IDC_EXCLUSIVE );
  219.     CheckRadioButton( hDlg, IDC_FOREGROUND, IDC_BACKGROUND,   IDC_FOREGROUND );
  220.     CheckRadioButton( hDlg, IDC_IMMEDIATE,  IDC_BUFFERED,     IDC_IMMEDIATE );
  221.  
  222.     UpdateUI( hDlg );
  223.  
  224.     return S_OK;
  225. }
  226.  
  227.  
  228.  
  229.  
  230. //-----------------------------------------------------------------------------
  231. // Name: UpdateUI()
  232. // Desc: Enables/disables the UI, and sets the dialog behavior text based on the UI
  233. //-----------------------------------------------------------------------------
  234. VOID UpdateUI( HWND hDlg )
  235. {
  236.     TCHAR   strExcepted[2048];
  237.     BOOL    bExclusive;
  238.     BOOL    bForeground;
  239.     BOOL    bImmediate;
  240.  
  241.     // Detrimine where the buffer would like to be allocated 
  242.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  243.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  244.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  245.  
  246.     if( g_pMouse )
  247.     {
  248.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("&Release Device") );
  249.         EnableMenuItem( GetMenu( hDlg ), IDM_RELEASEDEVICE, MF_ENABLED );
  250.         EnableMenuItem( GetMenu( hDlg ), IDM_CREATEDEVICE,  MF_GRAYED );
  251.         SetDlgItemText( hDlg, IDC_DATA, TEXT("") );
  252.  
  253.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), FALSE );
  254.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), FALSE );
  255.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), FALSE );
  256.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), FALSE );
  257.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), FALSE );
  258.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), FALSE );
  259.  
  260.         if( bExclusive )
  261.             SetDlgItemText( hDlg, IDC_HELP_TEXT, 
  262.                             TEXT("Press Enter to release the mouse device, ") \
  263.                             TEXT("and display the cursor again.") );
  264.     }
  265.     else
  266.     {
  267.         SetDlgItemText( hDlg, IDC_CREATEDEVICE, TEXT("&Create Device") );
  268.         EnableMenuItem( GetMenu( hDlg ), IDM_RELEASEDEVICE, MF_GRAYED );
  269.         EnableMenuItem( GetMenu( hDlg ), IDM_CREATEDEVICE,  MF_ENABLED );
  270.         SetDlgItemText( hDlg, IDC_DATA, TEXT("Device not created. Choose settings and click 'Create Device' then move mouse to see results") );   
  271.         SetDlgItemText( hDlg, IDC_HELP_TEXT, TEXT("") );
  272.  
  273.         EnableWindow( GetDlgItem( hDlg, IDC_EXCLUSIVE    ), TRUE );
  274.         EnableWindow( GetDlgItem( hDlg, IDC_NONEXCLUSIVE ), TRUE );
  275.         EnableWindow( GetDlgItem( hDlg, IDC_FOREGROUND   ), TRUE );
  276.         EnableWindow( GetDlgItem( hDlg, IDC_BACKGROUND   ), TRUE );
  277.         EnableWindow( GetDlgItem( hDlg, IDC_IMMEDIATE    ), TRUE );
  278.         EnableWindow( GetDlgItem( hDlg, IDC_BUFFERED     ), TRUE );
  279.     }
  280.  
  281.     // Figure what the user should expect based on the dialog choice
  282.     if( !bForeground && bExclusive )
  283.     {
  284.         _tcscpy( strExcepted, TEXT("For security reasons, background exclusive ") \
  285.                              TEXT("mouse access is not allowed.\n\n") );
  286.     }
  287.     else
  288.     {
  289.         if( bForeground )
  290.         {
  291.             _tcscpy( strExcepted, TEXT("Foreground cooperative level means that the ") \
  292.                                  TEXT("application has access to data only when in the ") \
  293.                                  TEXT("foreground or, in other words, has the input focus. ") \
  294.                                  TEXT("If the application moves to the background, ") \
  295.                                  TEXT("the device is automatically unacquired, or made ") \
  296.                                  TEXT("unavailable.\n\n") );
  297.         }
  298.         else
  299.         {
  300.             _tcscpy( strExcepted, TEXT("Background cooperative level really means ") \
  301.                                  TEXT("foreground and background. A device with a ") \
  302.                                  TEXT("background cooperative level can be acquired ") \
  303.                                  TEXT("and used by an application at any time.\n\n") );
  304.         }
  305.  
  306.         if( bExclusive )
  307.         {
  308.             _tcscat( strExcepted, TEXT("Exclusive mode prevents other applications from ") \
  309.                                  TEXT("also acquiring the device exclusively. The fact ") \
  310.                                  TEXT("that your application is using a device at the ") \
  311.                                  TEXT("exclusive level does not mean that other ") \
  312.                                  TEXT("applications cannot get data from the device. ") \
  313.                                  TEXT("Windows itself requires exclusive access to the ") \
  314.                                  TEXT("mouse because mouse events such as a click on ") \
  315.                                  TEXT("an inactive window could force an application ") \
  316.                                  TEXT("to unacquire the device, with potentially harmful ") \
  317.                                  TEXT("results, such as a loss of data from the input ") \
  318.                                  TEXT("buffer. Therefore, when an application has ") \
  319.                                  TEXT("exclusive access to the mouse, Windows is not ") \
  320.                                  TEXT("allowed any access at all. No mouse messages are ") \
  321.                                  TEXT("generated. A further side effect is that the ") \
  322.                                  TEXT("cursor disappears. When accessing the menu, the sample ") \
  323.                                  TEXT("releases the mouse so the mouse is displayed again.\n\n"));
  324.         }
  325.         else
  326.         {
  327.             _tcscat( strExcepted, TEXT("Nonexclusive mode means that other applications ") \
  328.                                  TEXT("can acquire device in exclusive or nonexclusive mode.\n\n"));
  329.         }
  330.  
  331.         if( bImmediate )
  332.         {
  333.             _tcscat( strExcepted, TEXT("Immediate data is a snapshot of the current ") \
  334.                                  TEXT("state of a device. It provides no data about ") \
  335.                                  TEXT("what has happened with the device since the ") \
  336.                                  TEXT("last call, apart from implicit information that ") \
  337.                                  TEXT("you can derive by comparing the current state with ") \
  338.                                  TEXT("the last one. Events in between calls are lost.\n\n") );
  339.         }
  340.         else
  341.         {
  342.             _tcscat( strExcepted, TEXT("Buffered data is a record of events that are stored ") \
  343.                                  TEXT("until an application retrieves them. With buffered ") \
  344.                                  TEXT("data, events are stored until you are ready to deal ") \
  345.                                  TEXT("with them. If the buffer overflows, new data is lost.\n\n") );                             
  346.         }
  347.  
  348.         _tcscat( strExcepted, TEXT("The sample will read the mouse 12 times a second. ") \
  349.                              TEXT("Typically an application would poll the mouse ") \
  350.                              TEXT("much faster than this, but this slow rate is simply ") \
  351.                              TEXT("for the purposes of demonstration.") );
  352.     }
  353.  
  354.     // Tell the user what to expect
  355.     SetDlgItemText( hDlg, IDC_BEHAVIOR, strExcepted );
  356. }
  357.  
  358.  
  359.  
  360.  
  361. //-----------------------------------------------------------------------------
  362. // Name: OnCreateDevice()
  363. // Desc: Sets up the mouse device using the flags from the dialog.
  364. //-----------------------------------------------------------------------------
  365. HRESULT OnCreateDevice( HWND hDlg )
  366. {
  367.     HRESULT hr;
  368.     BOOL    bExclusive;
  369.     BOOL    bForeground;
  370.     BOOL    bImmediate;
  371.     DWORD   dwCoopFlags;
  372.  
  373.     // Cleanup any previous call first
  374.     KillTimer( hDlg, 0 );    
  375.     FreeDirectInput();
  376.  
  377.     // Detrimine where the buffer would like to be allocated 
  378.     bExclusive         = ( IsDlgButtonChecked( hDlg, IDC_EXCLUSIVE  ) == BST_CHECKED );
  379.     bForeground        = ( IsDlgButtonChecked( hDlg, IDC_FOREGROUND ) == BST_CHECKED );
  380.     bImmediate         = ( IsDlgButtonChecked( hDlg, IDC_IMMEDIATE  ) == BST_CHECKED );
  381.  
  382.     if( bExclusive )
  383.         dwCoopFlags = DISCL_EXCLUSIVE;
  384.     else
  385.         dwCoopFlags = DISCL_NONEXCLUSIVE;
  386.  
  387.     if( bForeground )
  388.         dwCoopFlags |= DISCL_FOREGROUND;
  389.     else
  390.         dwCoopFlags |= DISCL_BACKGROUND;
  391.  
  392.     // Create a DInput object
  393.     if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  394.                                          IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
  395.         return hr;
  396.     
  397.     // Obtain an interface to the system mouse device.
  398.     if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) )
  399.         return hr;
  400.     
  401.     // Set the data format to "mouse format" - a predefined data format 
  402.     //
  403.     // A data format specifies which controls on a device we
  404.     // are interested in, and how they should be reported.
  405.     //
  406.     // This tells DirectInput that we will be passing a
  407.     // DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
  408.     if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) )
  409.         return hr;
  410.     
  411.     // Set the cooperativity level to let DirectInput know how
  412.     // this device should interact with the system and with other
  413.     // DirectInput applications.
  414.     hr = g_pMouse->SetCooperativeLevel( hDlg, dwCoopFlags );
  415.     if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive )
  416.     {
  417.         FreeDirectInput();
  418.         MessageBox( hDlg, _T("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n")
  419.                           _T("For security reasons, background exclusive mouse\n")
  420.                           _T("access is not allowed."), 
  421.                           _T("Mouse"), MB_OK );
  422.         return S_OK;
  423.     }
  424.  
  425.     if( FAILED(hr) )
  426.         return hr;
  427.  
  428.     if( !bImmediate )
  429.     {
  430.         // IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
  431.         //
  432.         // DirectInput uses unbuffered I/O (buffer size = 0) by default.
  433.         // If you want to read buffered data, you need to set a nonzero
  434.         // buffer size.
  435.         //
  436.         // Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
  437.         //
  438.         // The buffer size is a DWORD property associated with the device.
  439.         DIPROPDWORD dipdw;
  440.         dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
  441.         dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  442.         dipdw.diph.dwObj        = 0;
  443.         dipdw.diph.dwHow        = DIPH_DEVICE;
  444.         dipdw.dwData            = SAMPLE_BUFFER_SIZE; // Arbitary buffer size
  445.  
  446.         if( FAILED( hr = g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
  447.             return hr;
  448.     }
  449.  
  450.     // Acquire the newly created device
  451.     g_pMouse->Acquire();
  452.  
  453.     // Set a timer to go off 12 times a second, to read input
  454.     // Note: Typically an application would poll the mouse
  455.     //       much faster than this, but this slow rate is simply 
  456.     //       for the purposes of demonstration
  457.     SetTimer( hDlg, 0, 1000 / 12, NULL );
  458.  
  459.     return S_OK;
  460. }
  461.  
  462.  
  463.  
  464.  
  465. //-----------------------------------------------------------------------------
  466. // Name: ReadImmediateData()
  467. // Desc: Read the input device's state when in immediate mode and display it.
  468. //-----------------------------------------------------------------------------
  469. HRESULT ReadImmediateData( HWND hDlg )
  470. {
  471.     HRESULT       hr;
  472.     TCHAR         strNewText[128] = TEXT("");   // Output string
  473.     DIMOUSESTATE2 dims2;      // DirectInput mouse state structure
  474.  
  475.     if( NULL == g_pMouse ) 
  476.         return S_OK;
  477.     
  478.     // Get the input's device state, and put the state in dims
  479.     ZeroMemory( &dims2, sizeof(dims2) );
  480.     hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dims2 );
  481.     if( FAILED(hr) ) 
  482.     {
  483.         // DirectInput may be telling us that the input stream has been
  484.         // interrupted.  We aren't tracking any state between polls, so
  485.         // we don't have any special reset that needs to be done.
  486.         // We just re-acquire and try again.
  487.         
  488.         // If input is lost then acquire and keep trying 
  489.         hr = g_pMouse->Acquire();
  490.         while( hr == DIERR_INPUTLOST ) 
  491.             hr = g_pMouse->Acquire();
  492.  
  493.         // Update the dialog text 
  494.         if( hr == DIERR_OTHERAPPHASPRIO || 
  495.             hr == DIERR_NOTACQUIRED ) 
  496.             SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  497.  
  498.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  499.         // may occur when the app is minimized or in the process of 
  500.         // switching, so just try again later 
  501.         return S_OK; 
  502.     }
  503.     
  504.     // The dims structure now has the state of the mouse, so 
  505.     // display mouse coordinates (x, y, z) and buttons.
  506.     _stprintf( strNewText, TEXT("(X=% 3.3d, Y=% 3.3d, Z=% 3.3d) B0=%c B1=%c B2=%c B3=%c B4=%c B5=%c B6=%c B7=%c"),
  507.                          dims2.lX, dims2.lY, dims2.lZ,
  508.                         (dims2.rgbButtons[0] & 0x80) ? '1' : '0',
  509.                         (dims2.rgbButtons[1] & 0x80) ? '1' : '0',
  510.                         (dims2.rgbButtons[2] & 0x80) ? '1' : '0',
  511.                         (dims2.rgbButtons[3] & 0x80) ? '1' : '0',
  512.                         (dims2.rgbButtons[4] & 0x80) ? '1' : '0',
  513.                         (dims2.rgbButtons[5] & 0x80) ? '1' : '0',
  514.                         (dims2.rgbButtons[6] & 0x80) ? '1' : '0',
  515.                         (dims2.rgbButtons[7] & 0x80) ? '1' : '0');
  516.  
  517.     // Get the old text in the text box
  518.     TCHAR strOldText[128];
  519.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  520.     
  521.     // If nothing changed then don't repaint - avoid flicker
  522.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  523.         SetDlgItemText( hDlg, IDC_DATA, strNewText );
  524.     
  525.     return S_OK;
  526. }
  527.  
  528.  
  529.  
  530.  
  531. //-----------------------------------------------------------------------------
  532. // Name: ReadBufferedData()
  533. // Desc: Read the input device's state when in buffered mode and display it.
  534. //-----------------------------------------------------------------------------
  535. HRESULT ReadBufferedData( HWND hDlg )
  536. {
  537.     TCHAR              strNewText[128] = TEXT(""); 
  538.     DIDEVICEOBJECTDATA didod[ SAMPLE_BUFFER_SIZE ];  // Receives buffered data 
  539.     DWORD              dwElements;
  540.     DWORD              i;
  541.     HRESULT            hr;
  542.  
  543.     if( NULL == g_pMouse ) 
  544.         return S_OK;
  545.     
  546.     dwElements = SAMPLE_BUFFER_SIZE;
  547.     hr = g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
  548.                                      didod, &dwElements, 0 );
  549.     if( hr != DI_OK ) 
  550.     {
  551.         // We got an error or we got DI_BUFFEROVERFLOW.
  552.         //
  553.         // Either way, it means that continuous contact with the
  554.         // device has been lost, either due to an external
  555.         // interruption, or because the buffer overflowed
  556.         // and some events were lost.
  557.         //
  558.         // Consequently, if a button was pressed at the time
  559.         // the buffer overflowed or the connection was broken,
  560.         // the corresponding "up" message might have been lost.
  561.         //
  562.         // But since our simple sample doesn't actually have
  563.         // any state associated with button up or down events,
  564.         // there is no state to reset.  (In a real game, ignoring
  565.         // the buffer overflow would result in the game thinking
  566.         // a key was held down when in fact it isn't; it's just
  567.         // that the "up" event got lost because the buffer
  568.         // overflowed.)
  569.         //
  570.         // If we want to be cleverer, we could do a
  571.         // GetDeviceState() and compare the current state
  572.         // against the state we think the device is in,
  573.         // and process all the states that are currently
  574.         // different from our private state.
  575.         hr = g_pMouse->Acquire();
  576.         while( hr == DIERR_INPUTLOST ) 
  577.             hr = g_pMouse->Acquire();
  578.  
  579.         // Update the dialog text 
  580.         if( hr == DIERR_OTHERAPPHASPRIO || 
  581.             hr == DIERR_NOTACQUIRED ) 
  582.             SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
  583.  
  584.         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
  585.         // may occur when the app is minimized or in the process of 
  586.         // switching, so just try again later 
  587.         return S_OK; 
  588.     }
  589.  
  590.     if( FAILED(hr) )  
  591.         return hr;
  592.  
  593.     // Study each of the buffer elements and process them.
  594.     //
  595.     // Since we really don't do anything, our "processing"
  596.     // consists merely of squirting the name into our
  597.     // local buffer.
  598.     for( i = 0; i < dwElements; i++ ) 
  599.     {
  600.         // this will display then scan code of the key
  601.         // plus a 'D' - meaning the key was pressed 
  602.         //   or a 'U' - meaning the key was released
  603.         switch( didod[ i ].dwOfs )
  604.         {
  605.             case DIMOFS_BUTTON0:
  606.                 _tcscat( strNewText, TEXT("B0") );
  607.                 break;
  608.  
  609.             case DIMOFS_BUTTON1:
  610.                 _tcscat( strNewText, TEXT("B1") );
  611.                 break;
  612.  
  613.             case DIMOFS_BUTTON2:
  614.                 _tcscat( strNewText, TEXT("B2") );
  615.                 break;
  616.  
  617.             case DIMOFS_BUTTON3:
  618.                 _tcscat( strNewText, TEXT("B3") );
  619.                 break;
  620.  
  621.             case DIMOFS_BUTTON4:
  622.                 _tcscat( strNewText, TEXT("B4") );
  623.                 break;
  624.  
  625.             case DIMOFS_BUTTON5:
  626.                 _tcscat( strNewText, TEXT("B5") );
  627.                 break;
  628.  
  629.             case DIMOFS_BUTTON6:
  630.                 _tcscat( strNewText, TEXT("B6") );
  631.                 break;
  632.  
  633.             case DIMOFS_BUTTON7:
  634.                 _tcscat( strNewText, TEXT("B7") );
  635.                 break;
  636.  
  637.             case DIMOFS_X:
  638.                 _tcscat( strNewText, TEXT("X") );
  639.                 break;
  640.  
  641.             case DIMOFS_Y:
  642.                 _tcscat( strNewText, TEXT("Y") );
  643.                 break;
  644.  
  645.             case DIMOFS_Z:
  646.                 _tcscat( strNewText, TEXT("Z") );
  647.                 break;
  648.  
  649.             default:
  650.                 _tcscat( strNewText, TEXT("") );
  651.         }
  652.  
  653.         switch( didod[ i ].dwOfs )
  654.         {
  655.             case DIMOFS_BUTTON0:
  656.             case DIMOFS_BUTTON1:
  657.             case DIMOFS_BUTTON2:
  658.             case DIMOFS_BUTTON3:
  659.             case DIMOFS_BUTTON4:
  660.             case DIMOFS_BUTTON5:
  661.             case DIMOFS_BUTTON6:
  662.             case DIMOFS_BUTTON7:
  663.                 if( didod[ i ].dwData & 0x80 )
  664.                     _tcscat( strNewText, TEXT("U ") );
  665.                 else
  666.                     _tcscat( strNewText, TEXT("D ") );
  667.                 break;
  668.  
  669.             case DIMOFS_X:
  670.             case DIMOFS_Y:
  671.             case DIMOFS_Z:
  672.             {
  673.                 TCHAR strCoordValue[20];
  674.                 wsprintf( strCoordValue, TEXT("%d "), didod[ i ].dwData );
  675.                 _tcscat( strNewText, strCoordValue );
  676.                 break;
  677.             }
  678.         }
  679.     }
  680.  
  681.     // Get the old text in the text box
  682.     TCHAR strOldText[128];
  683.     GetDlgItemText( hDlg, IDC_DATA, strOldText, 127 );
  684.  
  685.     // If nothing changed then don't repaint - avoid flicker
  686.     if( 0 != lstrcmp( strOldText, strNewText ) ) 
  687.         SetDlgItemText( hDlg, IDC_DATA, strNewText );    
  688.  
  689.     return S_OK;
  690. }
  691.  
  692.  
  693.  
  694.  
  695. //-----------------------------------------------------------------------------
  696. // Name: FreeDirectInput()
  697. // Desc: Initialize the DirectInput variables.
  698. //-----------------------------------------------------------------------------
  699. VOID FreeDirectInput()
  700. {
  701.     // Unacquire the device one last time just in case 
  702.     // the app tried to exit while the device is still acquired.
  703.     if( g_pMouse ) 
  704.         g_pMouse->Unacquire();
  705.     
  706.     // Release any DirectInput objects.
  707.     SAFE_RELEASE( g_pMouse );
  708.     SAFE_RELEASE( g_pDI );
  709. }
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.